package com.mls.wms.android.model;

import com.mls.wms.android.util.JSONUtils;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by 2014-400 on 2015-08-31.
 */
public class JsonParser {
    /**
     * json字符串解析
     *
     * @param json
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T fromJson(String json, Class<T> cls) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return fromJson(json, cls, sdf);
    }

    /**
     * json字符串解析
     *
     * @param json
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T fromJson(JSONObject json, Class<T> cls) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return fromJson(json, cls, sdf);
    }

    /**
     * json字符串解析
     *
     * @param json
     * @param cls
     * @param sdf
     * @param <T>
     * @return
     */
    public static <T> T fromJson(String json, Class<T> cls, SimpleDateFormat sdf) {
        T o = null;
        try {
            Map<String, Method> methodMap = new HashMap<String, Method>();
            Method[] methods = cls.getMethods();
            for (Method m : methods) {
                String name = m.getName().toUpperCase();
                //set方法
                if (name.startsWith("SET") || name.startsWith("IS")) {
                    methodMap.put(name.substring(3), m);
                }
            }

            Map<String, String> map = JSONUtils.parseKeyAndValueToMap(json);
            o = cls.newInstance();
            Iterator<Map.Entry<String, String>> itr = map.entrySet().iterator();
            while (itr.hasNext()) {
                Map.Entry<String, String> entry = itr.next();
                String key = entry.getKey().toString().toUpperCase();

                if (methodMap.containsKey(key)) {
                    Method _m = methodMap.get(key);
                    Class<?> c = _m.getParameterTypes()[0];

                    if (c.getName().equals("int")) {
                        _m.invoke(o, Integer.parseInt(entry.getValue().toString()));
                    } else if (c.getName().equals("long")) {
                        _m.invoke(o, Long.parseLong(entry.getValue().toString()));
                    } else if (c == Integer.class) {
                        _m.invoke(o, (Integer) Integer.parseInt(entry.getValue().toString()));
                    } else if (c == Long.class) {
                        _m.invoke(o, (Long) Long.parseLong(entry.getValue().toString()));
                    } else if (c == String.class) {
                        _m.invoke(o, entry.getValue().toString());
                    } else if (c == Date.class) {
                        String date = entry.getValue().toString();
                        date = date.replaceFirst("T", " ");
                        _m.invoke(o, sdf.parse(date));
                    }
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return o;
    }

    /**
     * 解析json字符串
     *
     * @param json
     * @param cls
     * @param sdf
     * @param <T>
     * @return
     */
    public static <T> T fromJson(JSONObject json, Class<T> cls, SimpleDateFormat sdf) {
        T o = null;
        try {
            Map<String, Method> methodMap = new HashMap<String, Method>();
            Method[] methods = cls.getMethods();
            for (Method m : methods) {
                String name = m.getName().toUpperCase();
                //set方法
                if (name.startsWith("SET") || name.startsWith("IS")) {
                    methodMap.put(name.substring(3), m);
                }
            }

            Map<String, String> map = JSONUtils.parseKeyAndValueToMap(json);
            o = cls.newInstance();
            Iterator<Map.Entry<String, String>> itr = map.entrySet().iterator();
            while (itr.hasNext()) {
                Map.Entry<String, String> entry = itr.next();
                String key = entry.getKey().toString().toUpperCase();

                if (methodMap.containsKey(key)) {
                    Method _m = methodMap.get(key);
                    Class<?> c = _m.getParameterTypes()[0];

                    if (c.getName().equals("int")) {
                        _m.invoke(o, Integer.parseInt(entry.getValue().toString()));
                    } else if (c.getName().equals("long")) {
                        _m.invoke(o, Long.parseLong(entry.getValue().toString()));
                    } else if (c == Integer.class) {
                        _m.invoke(o, (Integer) Integer.parseInt(entry.getValue().toString()));
                    } else if (c == Long.class) {
                        _m.invoke(o, (Long) Long.parseLong(entry.getValue().toString()));
                    } else if (c == String.class) {
                        _m.invoke(o, entry.getValue().toString());
                    } else if (c == Date.class) {
                        String date = entry.getValue().toString();
                        date = date.replaceFirst("T", " ");
                        _m.invoke(o, sdf.parse(date));
                    }
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return o;
    }


    /**
     * 解析Json数组字符串
     *
     * @param json
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> List<T> fromJsons(String json, Class<T> cls) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return fromJsons(json, cls, sdf);
    }

    /**
     * 解析Json数组字符串
     *
     * @param json
     * @param cls
     * @param sdf
     * @param <T>
     * @return
     */
    public static <T> List<T> fromJsons(String json, Class<T> cls, SimpleDateFormat sdf) {
        List<T> list = new ArrayList<T>();
        try {
            Map<String, Method> methodMap = new HashMap<String, Method>();
            Method[] methods = cls.getMethods();
            for (Method m : methods) {
                String name = m.getName().toUpperCase();
                //set方法
                if (name.startsWith("SET") || name.startsWith("IS")) {
                    methodMap.put(name.substring(3), m);
                }
            }

            JSONArray array = new JSONArray(json);
            if (array == null || array.length() == 0) {
                return list;
            }
            //遍历Json数组对象
            for (int i = 0; i < array.length(); i++) {
                JSONObject obj = array.getJSONObject(i);
                T o = fromJson(obj, cls, sdf);
                if (o != null) {
                    list.add(o);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }
}
